/*
*******************************************************************************
*                     《手把手教你学51单片机(C语言版)》
* 文件名：main.c
* 描  述：第5章 课后练习
* 版本号：v1.0.0
* 备  注：利用定时器实现左右移动的流水灯
*******************************************************************************
*/
#include <reg52.h>

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

void main()
{
	//声明语句
	unsigned char cnt = 0;	//定时器计数用
	unsigned char i = 0;	//移位控制用
	unsigned char flag = 0;	//控制左移还是右移用
	//执行语句
	ENLED = 0;	//使能U3（74H138）
	ADDR3 = 1;	//使LEDS6为低电平来让LED所在的三极管Q16导通
	ADDR2 = 1;
	ADDR1 = 1;
	ADDR0 = 0;
	
	TMOD = 0x01;	//设置定时器模式寄存器为T0的工作模式1
	TH0 = 0xB8;	//定时器0.02s
	TL0 = 0x00;
	TR0 = 1;	//启动T0
	while(1)
	{
		if(flag == 0)	//如果flag为0说明要左移
		{
			if(TF0 == 1)	//判断定时器是否溢出
			{
				TF0 = 0;	//定时器溢出后，清除中断标志（软件清零）
				TH0 = 0xB8;	//定时器溢出后要重新计数，所以要重新赋值从0xB8开始计数
				TL0 = 0x00;
				cnt++;
				if(cnt >= 50)	//T0溢出50次就达到1秒了
				{
					P0 = ~(0x01 << i);	//达到1秒后进行左移
					cnt = 0;	//将cnt清零
					i++;	//移动位数要加1
					if(i >= 7)	//如果移动位数到7说明LED移动到最后一个了
					{
						i = 0;	//将i清零
						flag = 1;	//将flag置1，接下来将要右移
					}
				}
			}
		}else	//如果flag为1说明要右移
		{
			if(TF0 == 1)
			{
				TF0 = 0;
				TH0 = 0xB8;
				TL0 = 0x00;
				cnt++;
				if(cnt >= 50)
				{
					P0 = ~(0x80 >> i);
					cnt = 0;
					i++;
					if(i >= 7)
					{
						i = 0;
						flag = 0;
					}
				}
			}
		}
	}
}